package com.zhou.system.management.conf;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.util.ClassUtils;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;

import static java.util.Optional.ofNullable;


@Configuration
@EnableSwagger2WebMvc
@Import(BeanValidatorPluginsConfiguration.class)
public class Knife4jConfig {

    @Value("${knife4j.enable:true}")
    private boolean swaggerEnable;

    @Bean(value = "defaultApi1")
    public Docket defaultApi1() {
        String basePackage1 = "com.zhou.system.management.controller";
        String basePackage2 = "com.zhou.common.operator.log.web.controller";
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .enable(swaggerEnable)
                .apiInfo(new ApiInfoBuilder()
                        //.title("swagger-bootstrap-ui-demo RESTful APIs")
                        .description("测试项目")
                        .termsOfServiceUrl("http://www.xx.com/")
                        .contact("xx@qq.com")
                        .version("1.0")
                        .build())
                //分组名称
                .groupName("2.X版本")
                .select()
                //这里指定Controller扫描包路径
                .apis(getBasePackages(basePackage1, basePackage2))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }

    @Bean(value = "defaultApi2")
    public Docket common() {
        String basePackages = "com.zhou.common.operator.log.web.controller";
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .enable(swaggerEnable)
                .apiInfo(new ApiInfoBuilder()
                        //.title("swagger-bootstrap-ui-demo RESTful APIs")
                        .description("测试项目")
                        .termsOfServiceUrl("http://www.xx.com/")
                        .contact("xx@qq.com")
                        .version("1.0")
                        .build())
                //分组名称
                .groupName("common")
                .select()
                //这里指定Controller扫描包路径
                .apis(getBasePackages(basePackages))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }


    private Predicate<RequestHandler> getBasePackages(String... basePackages) {
        List<Predicate<RequestHandler>> list = Lists.newArrayList();
        for (String basePackage : basePackages) {

            list.add(RequestHandlerSelectors.basePackage(basePackage));
        }
        return Predicates.or(list);
    }

    public static class RequestHandlerSelectors {

        public static Predicate<RequestHandler> basePackage(final String basePackage) {
            return input -> declaringClass(input).map(handlerPackage(basePackage)).orElse(true);
        }

        private static Optional<? extends Class<?>> declaringClass(RequestHandler input) {
            return ofNullable(input.declaringClass());
        }

        private static Function<Class<?>, Boolean> handlerPackage(final String basePackage) {
            return input -> ClassUtils.getPackageName(input).startsWith(basePackage);
        }

        public static Predicate<RequestHandler> withMethodAnnotation(final Class<? extends Annotation> annotation) {
            return input -> input.isAnnotatedWith(annotation);
        }
    }
}
